﻿using System.Collections.Generic;
using System.Data;
using System.Linq;
using DataScripter.Database;
using DataScripter.Scripting;
using DataScripter.Scripting.Filters;
using DataScripter.Scripting.ScriptDefinitions;
using DataScripter.UnitTests.Util;
using Moq;

namespace DataScripter.UnitTests.Factories
{
    static class Helper
    {
        public static ITableScriptRequest MockScriptRequest(string tableName)
        {
            Mock<IDatabaseStructure> databaseStructureMock = new Mock<IDatabaseStructure>();
            return new TableScriptRequest(tableName, databaseStructureMock.Object, 0);
        }

        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, ITableScriptRequest tableScriptRequest, string tableName)
        {
            IDictionary<string, ITableScriptRequest> scriptRequests = scriptDefinition.ScriptRequests ?? new Dictionary<string, ITableScriptRequest>();
            scriptRequests.Add(tableName, tableScriptRequest);
            return tableScriptRequest;
        }

        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, string tableName)
        {
            var scriptRequestMock = MockScriptRequest(tableName);
            return scriptDefinition.InstallScriptRequest(scriptRequestMock, tableName);
        }

        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, string tableName, IForeignKey foreignKey)
        {
            ITableScriptRequest tableScriptRequest = InstallScriptRequest(scriptDefinition, tableName);
            tableScriptRequest.Filters.Add(foreignKey.Name, new ForeignKeyFilter(foreignKey, tableScriptRequest, scriptDefinition));
            return tableScriptRequest;
        }
        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, string tableName, string whereClause, IForeignKey foreignKey)
        {
            ITableScriptRequest tableScriptRequest = InstallScriptRequest(scriptDefinition, tableName);
            tableScriptRequest.Filters.Add("WHERE", new WhereFilter(whereClause));
            tableScriptRequest.Filters.Add(foreignKey.Name, new ForeignKeyFilter(foreignKey, tableScriptRequest, scriptDefinition));
            return tableScriptRequest;
        }
        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, string tableName, IEnumerable<IForeignKey> foreignKeys)
        {
            ITableScriptRequest tableScriptRequest = InstallScriptRequest(scriptDefinition, tableName);
            foreach (IForeignKey foreignKey in foreignKeys)
            {
                tableScriptRequest.Filters.Add(foreignKey.Name, new ForeignKeyFilter(foreignKey, tableScriptRequest, scriptDefinition));
            }
            return tableScriptRequest;
        }
        public static ITableScriptRequest InstallScriptRequest(this IScriptDefinition scriptDefinition, string tableName, string whereClause)
        {
            ITableScriptRequest tableScriptRequest = InstallScriptRequest(scriptDefinition, tableName);
            tableScriptRequest.Filters.Add("WHERE", new WhereFilter(whereClause));
            return tableScriptRequest;
        }

        public static Mock<ITableStructure> InstallTableStructure(this ITableScriptRequest tableScriptRequestMock, IEnumerable<FieldInfo> fields, params int[] primaryKeyFields)
        {
            Mock<ITableStructure> tableStructureMock = new Mock<ITableStructure>();
            tableStructureMock.Setup(ts => ts.Fields).Returns(fields.ToDictionary(fieldInfo => fieldInfo.ColumnName));
            tableStructureMock.Setup(ts => ts.PrimaryKeyFields).Returns(primaryKeyFields.Select(pkf => fields.ElementAt(pkf)).ToList());
            tableScriptRequestMock.TableStructure = tableStructureMock.Object;
            return tableStructureMock;
        }
        public static IDataReader ConstructReader(this Mock<ITableStructure> tableStructureMock, IEnumerable<object[]> rows)
        {
            string[] fieldNames = tableStructureMock.Object.Fields.Values.Select(f => f.ColumnName).ToArray();
            StubResultSet stubResultSet = new StubResultSet(fieldNames, rows);
            StubDataReader stubDataReader = new StubDataReader(stubResultSet);
            return stubDataReader;
        }
    }
}
